﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kooboo.IoC;
using Kooboo.Commerce.Contexts.Customers;
using Kooboo.Domain;
using Kooboo.Commerce.Contexts.Orders;


namespace Kooboo.Commerce.Contexts.Carts
{
    public static class VistorBehavior
    {
        public static IQueryable<ICart> QueryCarts(this IVistor actor)
        {
            return ContextContainer.Current.Resolve<ICartRepository>().Carts;
        }

        public static ICart OpenCart(this IVistor actor, int? cartId)
        {
            ICart cart = null;

            var current_user = ContextContainer.Current.Resolve<Kooboo.Connect.User>();
            ICustomer current_customer = null;
            if (current_user != null)
                current_customer = current_user.GetCustomer();

            var repository = ContextContainer.Current.Resolve<ICartRepository>();
            if (current_customer == null)
            {
                if (cartId.HasValue)//open the anonymous cart
                {
                    cart = actor
                        .QueryCarts()
                        .Where(i => i.Id == cartId.Value && i.IsOrdered == false)
                        .FirstOrDefault();
                }


                if (cart == null)//create a anonymous cart
                {
                    cart = ObjectContainer.CreateInstance<ICart>();
                    cart.CreateDate = DateTime.Now;
                    repository.Post(cart);
                }
            }
            else
            {
                if (cartId.HasValue)//bind the customer to the anonymous cart
                {
                    cart = repository.Carts
                      .Where(i => i.Id == cartId.Value && i.IsOrdered == false
                          && (i.Customer == null || i.Customer.Id == current_customer.Id))
                      .FirstOrDefault();

                    if (cart != null)
                    {
                        if (cart.Customer == null)
                        {
                            //var customer = actor
                            //    .QueryCustomers()
                            //    .Where(i => i.UserName == current_user.Name)
                            //    .FirstOrDefault();

                            cart.Customer = current_customer;

                            repository.Put(cart);
                        }
                    }
                }


                if (cart == null)//get latest cart of the customer
                {
                    cart = repository.Carts
                        .Where(i => i.Customer != null && i.Customer.Id == current_customer.Id && i.IsOrdered == false)
                        .OrderByDescending(i => i.CreateDate)
                        .FirstOrDefault();

                    if (cart == null)
                    {
                        cart = ObjectContainer.CreateInstance<ICart>();
                        //var customer = actor
                        //    .QueryCustomers()
                        //    .Where(i => i.UserName == current_user.Name)
                        //    .FirstOrDefault();
                        cart.Customer = current_customer;
                        cart.CreateDate = DateTime.Now;

                        repository.Post(cart);
                    }
                }

            }


            return cart;
        }

        public static void Post(this IVistor actor, ICart cart)
        {


            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    var repository = ContextContainer.Current.Resolve<ICartRepository>();

                    Calculator.Calculate(cart);

                    repository.Post(cart);
                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static void Put(this IVistor actor, ICart cart)
        {
            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    var repository = ContextContainer.Current.Resolve<ICartRepository>();

                    Calculator.Calculate(cart);

                    repository.Put(cart);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static void Delete(this IVistor actor, ICart cart)
        {


            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    var repository = ContextContainer.Current.Resolve<ICartRepository>();
                    repository.Delete(cart);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static IOrder Order(this IVistor actor, ICart cart)
        {

            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    cart.IsOrdered = true;
                    actor.Put(cart);

                    var order = ObjectContainer.CreateInstance<IOrder>();
                    order.Address1 = cart.Address1;
                    order.Address2 = cart.Address2;
                    order.Cart = cart;
                    order.City = cart.City;
                    order.Country = cart.Country;
                    order.Coupon = cart.Coupon;
                    order.Customer = cart.Customer;
                    order.Discount = cart.Discount;
                    order.FirstName = cart.FirstName;
                    order.InsuredAmount = cart.InsuredAmount;
                    order.InvoiceAddress1 = cart.InvoiceAddress1;
                    order.InvoiceAddress2 = cart.InvoiceAddress2;
                    order.InvoiceCity = cart.InvoiceCity;
                    order.InvoiceCountry = cart.InvoiceCountry;
                    order.InvoiceFirstName = cart.InvoiceFirstName;
                    order.InvoiceLastName = cart.InvoiceLastName;
                    order.InvoicePhone = cart.InvoicePhone;
                    order.InvoicePostcode = cart.InvoicePostcode;
                    order.InvoiceState = cart.InvoiceState;
                    order.LastName = cart.LastName;
                    order.OrderDate = DateTime.Now;
                    //order.OrderStatus = OrderStatus.InProgress; add by zhenquan
                    order.OrderStatus = OrderStatus.PaymentPending;
                    order.PaymentMethodCost = cart.PaymentMethodCost;
                    order.PaymentName = cart.Payment.MethodName;
                    order.Phone = cart.Phone;
                    order.Postcode = cart.Postcode;
                    order.Remark = cart.Remark;
                    order.ShippingCost = cart.ShippingCost;
                    order.ShippingId = cart.Shipping.Id;
                    order.State = cart.State;
                    order.SubTotal = cart.SubTotal;
                    order.Total = cart.Total;
                    order.TotalDiscount = cart.TotalDiscount;
                    order.TotalTaxCost = cart.TotalTaxCost;
                    //order.TotalWeight


                    //order.Promotions
                    foreach (var item in cart.CartItems)
                    {
                        var orderitem = ObjectContainer.CreateInstance<IOrderItem>();
                        orderitem.Discount = item.Discount;
                        orderitem.Order = order;

                        foreach (var i in item.Product.ProductCustomFields)
                        {
                            var field = ObjectContainer.CreateInstance<IOrderItemCustomField>();
                            field.Name = i.CustomField.Name;
                            field.Value = i.Value;
                            orderitem.OrderItemCustomFields.Add(field);
                        }

                        foreach (var i in item.SaleItem.ProductVariations)
                        {
                            var field = ObjectContainer.CreateInstance<IOrderItemVariation>();
                            field.Name = i.Variation.Name;
                            field.Value = i.Value;

                            orderitem.OrderItemVariations.Add(field);
                        }

                        orderitem.ProductId = item.Product.Id;
                        orderitem.ProductName = item.ProductName;
                        //orderitem.Promotions
                        orderitem.Quantity = item.Quantity;
                        orderitem.UnitPrice = item.UnitPrice;
                        orderitem.SaleItemId = item.SaleItem.Id;
                        orderitem.SKU = item.SKU;
                        orderitem.SubTotal = item.SubTotal;
                        orderitem.TaxCost = item.TaxCost;
                        orderitem.Total = item.Total;

                        order.OrderItems.Add(orderitem);
                    }

                    var repository = ContextContainer.Current.Resolve<IOrderRepository>();

                    repository.Post(order);

                    transaction.Commit();

                    return order;
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }


            }
        }
    }
}
